<template>
    <div class="layer-control-panel">
        <div class="search-container">
            <input type="text" v-model="searchQuery" placeholder="搜索图层..." class="search-input">
        </div>

        <div v-for="group in filteredLayerGroups" :key="group.name" class="layer-group"
            :class="{ collapsed: collapsedGroups[group.name] }">
            <h5 @click="toggleGroup(group)">
                {{ group.label }}
            </h5>

            <transition name="slide">
                <div v-show="!collapsedGroups[group.name]" class="layer-group-content">
                    <draggable handle=".drag-handle" v-model="group.layers" group="layers" @end="onDragEnd(group.name)">
                        <div v-for="layer in group.layers" :key="layer.key" class="layer-item">
                            <div class="layer-header">
                                <span class="drag-handle">☰</span>
                                <input type="checkbox" v-model="layer.visible" @change="toggle(layer)" />
                                <span class="layer-icon" :style="{ backgroundColor: layer.color || '#409EFF' }"></span>
                                <span class="layer-name">{{ layer.name }}</span>
                                <span class="layer-toggle" @click.stop="zoomToLayer(layer)">
                                    {{ layer.visible ? '🔍' : '🔍' }}
                                </span>
                            </div>

                            <transition name="fade">
                                <div v-if="layer.visible" class="layer-controls">
                                    <input type="range" min="0" max="1" step="0.01" v-model.number="layer.opacity"
                                        @input="setOpacity(layer)" />
                                    <span>{{ Math.round(layer.opacity * 100) }}%</span>
                                </div>
                            </transition>
                        </div>
                    </draggable>
                </div>
            </transition>
        </div>
    </div>
</template>

<script>
import draggable from 'vuedraggable';

export default {
    components: { draggable },
    props: {
        map: Object,
        layerGroups: Array
    },
    data() {
        return {
            searchQuery: '',
            collapsedGroups: {},
            drag: false
        };
    },
    computed: {
        filteredLayerGroups() {
            if (!this.searchQuery) return this.layerGroups;

            const query = this.searchQuery.toLowerCase();
            return this.layerGroups.map(group => ({
                ...group,
                layers: group.layers.filter(layer =>
                    layer.name.toLowerCase().includes(query)
                )
            }));
        }
    },
    methods: {
        toggle(layer) {
            const olLayer = this.map.getLayers().getArray().find(l => l.get('name') === layer.key);
            if (olLayer) {
                olLayer.setVisible(layer.visible);
            }
        },
        setOpacity(layer) {
            const olLayer = this.map.getLayers().getArray().find(l => l.get('name') === layer.key);
            if (olLayer) {
                olLayer.setOpacity(layer.opacity);
            }
        },
        onDragEnd(groupName) {
            const group = this.layerGroups.find(g => g.name === groupName);
            const layerKeys = group.layers.map(l => l.key);
            const mapLayers = this.map.getLayers().getArray();

            layerKeys.forEach((key, newIndex) => {
                const layer = mapLayers.find(l => l.get('name') === key);
                if (layer) {
                    const oldIndex = mapLayers.indexOf(layer);
                    if (oldIndex !== -1 && oldIndex !== newIndex) {
                        this.map.getLayers().removeAt(oldIndex);
                        this.map.getLayers().insertAt(newIndex, layer);
                    }
                }
            });
        },
        toggleGroup(group) {
            this.$set(this.collapsedGroups, group.name, !this.collapsedGroups[group.name]);
        },
        toggleVisibility(layer) {
            layer.visible = !layer.visible;
            this.toggle(layer);
        },
        async zoomToLayer(layer) {
            // 如果图层不可见，则不执行跳转
            if (!layer.visible) return;

            // 获取 OpenLayers 图层对象
            const olLayer = this.map.getLayers().getArray().find(l => l.get('name') === layer.key);
            if (!olLayer) return;

            let extent = null;

            // 1. 尝试使用 getExtent() （适用于 VectorLayer、ImageLayer、TileLayer）
            extent = olLayer.getExtent();

            // 2. 如果无效，尝试从 source 获取 features （适用于 VectorSource）
            if (!extent || extent.length === 0) {
                const source = olLayer.getSource();
                if (source && typeof source.getFeatures === 'function') {
                    const features = source.getFeatures();
                    if (features.length > 0) {
                        const projection = source.getProjection();
                        extent = this.calculateFeaturesExtent(features, projection);
                    }
                }
            }

            // 3. 如果仍无 extent，尝试从 tileGrid 获取（适用于 TileLayer / GeoTIFF）
            if (!extent || extent.length === 0) {
                const source = olLayer.getSource();
                if (source && source.tileGrid && source.tileGrid.extent_) {
                    extent = source.tileGrid.extent_;
                }
            }

            // 4. 最终检查
            if (!extent || extent.length === 0) {
                alert('该图层暂无可用范围');
                return;
            }

            // 跳转到图层范围
            this.map.getView().fit(extent, {
                duration: 1000,
                padding: [50, 50, 50, 50],
                maxZoom: 18
            });
        },
        calculateFeaturesExtent(features, projection) {
            let extent = null;
            for (const feature of features) {
                const geom = feature.getGeometry();
                if (geom) {
                    let featExtent = geom.getExtent();

                    // 如果几何不是 EPSG:3857，进行转换
                    if (projection && !this.map.getView().getProjection().equals(projection)) {
                        featExtent = geom.clone().transform(projection, this.map.getView().getProjection()).getExtent();
                    }

                    if (!extent) {
                        extent = featExtent;
                    } else {
                        extent = [
                            Math.min(extent[0], featExtent[0]),
                            Math.min(extent[1], featExtent[1]),
                            Math.max(extent[2], featExtent[2]),
                            Math.max(extent[3], featExtent[3])
                        ];
                    }
                }
            }
            return extent;
        }
    }
};
</script>

<style scoped>
.layer-control-panel {
    position: absolute;
    top: 10px;
    left: calc(10px + 263px);
    z-index: 1000;
    background-color: #ffffff;
    padding: 16px;
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    width: 240px;
    max-height: 80vh;
    overflow-y: auto;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    transition: all 0.3s ease;
}

.layer-control-panel h4 {
    margin-top: 0;
    font-size: 16px;
    color: #2c3e50;
    text-align: center;
    margin-bottom: 12px;
    font-weight: bold;
    border-bottom: 1px solid #eaeaea;
    padding-bottom: 6px;
}

.layer-group {
    margin-bottom: 16px;
    padding-bottom: 8px;
    border-bottom: 1px solid #f0f0f0;
}

.layer-group:last-child {
    border-bottom: none;
    margin-bottom: 0;
}

.layer-group h5 {
    font-size: 14px;
    margin: 0 0 8px;
    color: #34495e;
    font-weight: 600;
    display: flex;
    justify-content: space-between;
    align-items: center;
    cursor: pointer;
    padding: 4px 8px;
    border-radius: 4px;
    transition: background-color 0.2s ease;
}

.layer-group h5:hover {
    background-color: #f7f9fb;
}

.layer-group h5::after {
    content: '▼';
    font-size: 10px;
    transition: transform 0.3s ease;
}

.layer-group.collapsed h5::after {
    transform: rotate(-90deg);
}

.layer-item {
    padding: 6px 12px;
    background-color: #f9f9f9;
    border-radius: 6px;
    margin: 4px 0;
    transition: all 0.2s ease;
}

.layer-item:hover {
    background-color: #ecf0f1;
    transform: translateX(2px);
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}

.layer-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    cursor: grab;
}

.layer-name {
    flex: 1;
    font-size: 14px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    margin-right: 8px;
}

.layer-toggle {
    cursor: pointer;
    font-size: 16px;
    margin-left: 8px;
    color: #666;
    transition: color 0.2s ease;
}

.layer-toggle:hover {
    color: #333;
}

.layer-controls {
    display: flex;
    align-items: center;
    margin-top: 6px;
    padding-top: 6px;
    border-top: 1px solid #eee;
}

.layer-controls input[type="range"] {
    flex: 1;
    margin-right: 8px;
    cursor: ew-resize;
}

.layer-controls span {
    font-size: 12px;
    color: #888;
    min-width: 36px;
    text-align: right;
}

/* 拖拽时的样式 */
.draggable-element:active {
    opacity: 0.7;
}

/* 折叠动画 */
.slide-enter-active,
.slide-leave-active {
    transition: max-height 0.3s ease-out;
    overflow: hidden;
}

.slide-enter,
.slide-leave-to {
    max-height: 0;
}

/* 深色模式支持（可选） */
@media (prefers-color-scheme: dark) {
    .layer-control-panel {
        background-color: #2d2d2d;
        color: #fff;
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
    }

    .layer-control-panel h4 {
        color: #ddd;
        border-color: #444;
    }

    .layer-group {
        border-color: #3a3a3a;
    }

    .layer-group h5 {
        color: #ccc;
        background-color: transparent;
    }

    .layer-group h5:hover {
        background-color: #3a3a3a;
    }

    .layer-item {
        background-color: #3a3a3a;
    }

    .layer-item:hover {
        background-color: #4a4a4a;
    }
}

.search-container {
    margin-bottom: 12px;
}

.search-input {
    width: 100%;
    padding: 6px 10px;
    border: 1px solid #ddd;
    border-radius: 4px;
    font-size: 13px;
    outline: none;
    transition: border-color 0.2s ease;
}

.search-input:focus {
    border-color: #409EFF;
    box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}
</style>